home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / EnvelopeState.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  28.6 KB  |  858 lines  |  [TEXT/KAHL]

  1. /* EnvelopeState.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define ShowMeEnvelopeRec
  31. #include "EnvelopeState.h"
  32. #include "FastFixedPoint.h"
  33. #include "Envelope.h"
  34. #include "Memory.h"
  35. #include "LinearTransition.h"
  36. #include "Frequency.h"
  37. #include "FloatingPoint.h"
  38.  
  39.  
  40. /* local prototypes */
  41. static void                        EnvStepToNextInterval(EvalEnvelopeRec* State);
  42. static FastFixedType    EnvUpdateLinearAbsolute(EvalEnvelopeRec* State);
  43. static FastFixedType    EnvUpdateLinearDecibels(EvalEnvelopeRec* State);
  44. static FastFixedType    EnvUpdateSustain(EvalEnvelopeRec* State);
  45.  
  46.  
  47. typedef struct OneEnvPhaseRec
  48.     {
  49.         /* how many envelope cycles does this phase last */
  50.         long                                            Duration;
  51.         /* what amplitude are we trying to attain */
  52.         FastFixedType                            FinalAmplitude;
  53.         /* what does the curve look like */
  54.         EnvTransTypes                            TransitionType;
  55.         /* way of deriving the target */
  56.         EnvTargetTypes                        TargetType;
  57.  
  58.         /* pointer for making linked lists */
  59.         struct OneEnvPhaseRec*        PhaseLink;
  60.     } OneEnvPhaseRec;
  61.  
  62.  
  63. struct EvalEnvelopeRec
  64.     {
  65.         /* number of envelope phases. 0 phases means the envelope produces constant value */
  66.         long                                            NumPhases;
  67.         /* list of definitions for each transition phase.  when this goes NIL, then */
  68.         /* we are done. */
  69.         OneEnvPhaseRec*                        CurrentPhaseRecord;
  70.         /* this remembers the first phase */
  71.         OneEnvPhaseRec*                        PhaseListHead;
  72.  
  73.         /* phase at which first sustain occurs. (released by key-up) */
  74.         /* if the value of this is N, then sustain will occur after phase N has */
  75.         /* completed.  if it is 0, then sustain will occur after phase 0 has completed. */
  76.         /* if it is -1, then sustain will not occur.  sustain may not be NumPhases since */
  77.         /* that would be the end of envelope and would be the same as final value hold. */
  78.         long                                            SustainPhase1;
  79.         long                                            OriginalSustainPhase1;
  80.         SustainTypes                            SustainPhase1Type;
  81.         /* phase at which second sustain occurs. */
  82.         long                                            SustainPhase2;
  83.         long                                            OriginalSustainPhase2;
  84.         SustainTypes                            SustainPhase2Type;
  85.         /* phase at which note-end sustain occurs */
  86.         long                                            SustainPhase3;
  87.         long                                            OriginalSustainPhase3;
  88.         SustainTypes                            SustainPhase3Type;
  89.  
  90.         /* what output phase are we generating right now.  this is the phase index of */
  91.         /* the record currently in CurrentPhaseRecord. */
  92.         long                                            Phase;
  93.  
  94.         /* what is the origin phase */
  95.         long                                            Origin;
  96.  
  97.         /* this is the envelope transition generator */
  98.         LinearTransRec*                        LinearTransition;
  99.         /* this is the countdown for this linear transition.  this is NOT used for */
  100.         /* linear-decibel transitions.  instead, we hack it ourselves. */
  101.         long                                            LinearTransitionCounter;
  102.         /* stuff needed for linear-decibel transitions */
  103.         long                                            LinearTransitionTotalDuration;
  104.         float                                            InitialDecibels;
  105.         float                                            FinalDecibels;
  106.         /* hold value for when we are sustaining */
  107.         FastFixedType                            LastOutputtedValue;
  108.  
  109.         /* number of cycles of the envelope that occur before the origin */
  110.         long                                            PreOriginTime;
  111.  
  112.         /* this function performs one update cycle */
  113.         FastFixedType                            (*EnvelopeUpdate)(EvalEnvelopeRec* State);
  114.  
  115.         /* flag indicating that envelope has finished evaluating the last phase */
  116.         MyBoolean                                    EnvelopeHasFinished;
  117.  
  118.         /* we remember the template that was used to construct us */
  119.         EnvelopeRec*                            Template;
  120.  
  121.         /* pointer for maintaining the free list */
  122.         EvalEnvelopeRec*                    GarbageLink;
  123.     };
  124.  
  125.  
  126. static EvalEnvelopeRec*            EnvelopeStateFreeList = NIL;
  127. static OneEnvPhaseRec*            EnvelopeEntryFreeList = NIL;
  128.  
  129.  
  130. /* flush cached envelope state records */
  131. void                                FlushEvalEnvelopeStateRecords(void)
  132.     {
  133.         while (EnvelopeStateFreeList != NIL)
  134.             {
  135.                 EvalEnvelopeRec*        Temp;
  136.  
  137.                 Temp = EnvelopeStateFreeList;
  138.                 EnvelopeStateFreeList = EnvelopeStateFreeList->GarbageLink;
  139.                 ReleasePtr((char*)Temp);
  140.             }
  141.  
  142.         while (EnvelopeEntryFreeList != NIL)
  143.             {
  144.                 OneEnvPhaseRec*            Temp;
  145.  
  146.                 Temp = EnvelopeEntryFreeList;
  147.                 EnvelopeEntryFreeList = EnvelopeEntryFreeList->PhaseLink;
  148.                 ReleasePtr((char*)Temp);
  149.             }
  150.     }
  151.  
  152.  
  153. #if DEBUG
  154. static void                    DebugCheckState(EvalEnvelopeRec* State)
  155.     {
  156.         EvalEnvelopeRec*    Scan;
  157.  
  158.         Scan = EnvelopeStateFreeList;
  159.         while (Scan != NIL)
  160.             {
  161.                 if (Scan == State)
  162.                     {
  163.                         PRERR(ForceAbort,"DebugCheckState:  released envelope record passed in");
  164.                     }
  165.                 Scan = Scan->GarbageLink;
  166.             }
  167.     }
  168. #else
  169. #define DebugCheckState(x) ((void)0)
  170. #endif
  171.  
  172.  
  173. #if DEBUG
  174. static void                    DebugCheckPhase(OneEnvPhaseRec* Phase)
  175.     {
  176.         OneEnvPhaseRec*        Scan;
  177.  
  178.         Scan = EnvelopeEntryFreeList;
  179.         while (Scan != NIL)
  180.             {
  181.                 if (Scan == Phase)
  182.                     {
  183.                         PRERR(ForceAbort,"DebugCheckPhase:  released envelope phase passed in");
  184.                     }
  185.                 Scan = Scan->PhaseLink;
  186.             }
  187.     }
  188. #else
  189. #define DebugCheckPhase(x) ((void)0)
  190. #endif
  191.  
  192.  
  193. /* dispose of an envelope state record */
  194. void                                DisposeEnvelopeStateRecord(EvalEnvelopeRec* State)
  195.     {
  196.         OneEnvPhaseRec*        PhaseScan;
  197.  
  198.         CheckPtrExistence(State);
  199.         DebugCheckState(State);
  200.  
  201.         DisposeLinearTransition(State->LinearTransition);
  202.         PhaseScan = State->PhaseListHead;
  203.         while (PhaseScan != NIL)
  204.             {
  205.                 OneEnvPhaseRec*            Temp;
  206.  
  207.                 Temp = PhaseScan;
  208.                 DebugCheckPhase(Temp);
  209.                 PhaseScan = PhaseScan->PhaseLink;
  210.                 Temp->PhaseLink = EnvelopeEntryFreeList;
  211.                 EnvelopeEntryFreeList = Temp;
  212.             }
  213.         State->GarbageLink = EnvelopeStateFreeList;
  214.         EnvelopeStateFreeList = State;
  215.     }
  216.  
  217.  
  218. /* create a new envelope state record.  Accent factors have no effect with a value */
  219. /* of 1, attenuate at smaller values, and amplify at larger values. */
  220. EvalEnvelopeRec*        NewEnvelopeStateRecord(struct EnvelopeRec* Template,
  221.                                             float Accent1, float Accent2, float Accent3, float Accent4,
  222.                                             float FrequencyHertz, float Loudness, float HurryUp,
  223.                                             float TicksPerSecond, long* PreOriginTime)
  224.     {
  225.         EvalEnvelopeRec*    State;
  226.         long                            Scan;
  227.         OneEnvPhaseRec*        PhaseTail;
  228.  
  229.         CheckPtrExistence(Template);
  230.         /* we can only handle it if the envelope definition's internal values are floats */
  231.         /* this generates a type error if they aren't */
  232.         EXECUTE((void)((EnvNumberType*)NIL != (float*)NIL);)
  233.  
  234.         /* allocate state record */
  235.         if (EnvelopeStateFreeList != NIL)
  236.             {
  237.                 State = EnvelopeStateFreeList;
  238.                 EnvelopeStateFreeList = EnvelopeStateFreeList->GarbageLink;
  239.             }
  240.          else
  241.             {
  242.                 State = (EvalEnvelopeRec*)AllocPtrCanFail(sizeof(EvalEnvelopeRec),
  243.                     "EvalEnvelopeRec");
  244.                 if (State == NIL)
  245.                     {
  246.                         return NIL;
  247.                     }
  248.             }
  249.  
  250.         /* fill in the fields */
  251.         State->NumPhases = Template->NumPhases;
  252.         State->SustainPhase1 = Template->SustainPhase1;
  253.         State->OriginalSustainPhase1 = Template->SustainPhase1;
  254.         State->SustainPhase1Type = Template->SustainPhase1Type;
  255.         State->SustainPhase2 = Template->SustainPhase2;
  256.         State->OriginalSustainPhase2 = Template->SustainPhase2;
  257.         State->SustainPhase2Type = Template->SustainPhase2Type;
  258.         State->SustainPhase3 = Template->SustainPhase3;
  259.         State->OriginalSustainPhase3 = Template->SustainPhase3;
  260.         State->SustainPhase3Type = Template->SustainPhase3Type;
  261.         State->Phase = -1;
  262.         State->Origin = Template->Origin;
  263.  
  264.         /* build initial delay transition */
  265.         State->LinearTransition = NewLinearTransition(0,0,1);
  266.         if (State->LinearTransition == NIL)
  267.             {
  268.              FailurePoint1:
  269.                 State->GarbageLink = EnvelopeStateFreeList;
  270.                 EnvelopeStateFreeList = State;
  271.                 return NIL;
  272.             }
  273.         State->LinearTransitionCounter = 0;
  274.         State->LinearTransitionTotalDuration = 0;
  275.         State->EnvelopeUpdate = &EnvUpdateLinearAbsolute;
  276.         State->LastOutputtedValue = 0;
  277.         State->EnvelopeHasFinished = False;
  278.  
  279.         State->Template = Template;
  280.  
  281.         /* build list of nodes */
  282.         PhaseTail = NIL;
  283.         State->CurrentPhaseRecord = NIL;
  284.         State->PhaseListHead = NIL;
  285.         State->PreOriginTime = 0;
  286.         for (Scan = 0; Scan < State->NumPhases; Scan += 1)
  287.             {
  288.                 OneEnvPhaseRec*            Phase;
  289.  
  290.                 /* allocate phase record */
  291.                 if (EnvelopeEntryFreeList != NIL)
  292.                     {
  293.                         Phase = EnvelopeEntryFreeList;
  294.                         EnvelopeEntryFreeList = EnvelopeEntryFreeList->PhaseLink;
  295.                     }
  296.                  else
  297.                     {
  298.                         Phase = (OneEnvPhaseRec*)AllocPtrCanFail(sizeof(OneEnvPhaseRec),
  299.                             "OneEnvPhaseRec");
  300.                         if (Phase == NIL)
  301.                             {
  302.                              FailurePoint2:
  303.                                 while (State->PhaseListHead != NIL)
  304.                                     {
  305.                                         Phase = State->PhaseListHead;
  306.                                         State->PhaseListHead = State->PhaseListHead->PhaseLink;
  307.                                         Phase->PhaseLink = EnvelopeEntryFreeList;
  308.                                         EnvelopeEntryFreeList = Phase;
  309.                                     }
  310.                                 goto FailurePoint1;
  311.                             }
  312.                     }
  313.  
  314.                 /* fill in phase record parameters */
  315.                 PRNGCHK(Template->PhaseArray,&(Template->PhaseArray[Scan]),
  316.                     sizeof(Template->PhaseArray[Scan]));
  317.                 Phase->TransitionType = Template->PhaseArray[Scan].TransitionType;
  318.                 Phase->TargetType = Template->PhaseArray[Scan].TargetType;
  319.                 /* calculate the total duration.  the effect of accents is this: */
  320.                 /*  - the accent is the base-2 log of a multiplier for the rate.  a value of 0 */
  321.                 /*    does not change the rate.  -1 halves the rate, and 1 doubles the rate. */
  322.                 /*  - the accent scaling factor is the base-2 log for scaling the accent. */
  323.                 /*    a value of 0 eliminates the effect of the accent, a value of 1 does not */
  324.                 /*    scale the accent. */
  325.                 /*  - pitch has two factors:  normalization point and rolloff.  rolloff */
  326.                 /*    determines how much the signal will decrease with each octave.  0 */
  327.                 /*    removes effect, 1 halfs signal with each octave.  normalization point */
  328.                 /*    determines what pitch will be the invariant point. */
  329.                 Phase->Duration = TicksPerSecond * HurryUp * Template->PhaseArray[Scan].Duration
  330.                     * FPOWER(2, - (Accent1 * Template->PhaseArray[Scan].Accent1Rate
  331.                         + Accent2 * Template->PhaseArray[Scan].Accent2Rate
  332.                         + Accent3 * Template->PhaseArray[Scan].Accent3Rate
  333.                         + Accent4 * Template->PhaseArray[Scan].Accent4Rate
  334.                         + (FLN(FrequencyHertz / Template->PhaseArray[Scan].FrequencyRateNormalization)
  335.                         / (float)LOG2) * Template->PhaseArray[Scan].FrequencyRateRolloff));
  336.                 /* the final amplitude scaling values are computed similarly to the rate */
  337.                 /* scaling values. */
  338.                 Phase->FinalAmplitude = Double2FastFixed(Template->PhaseArray[Scan].EndPoint
  339.                     * Template->OverallScalingFactor * Loudness
  340.                     * FPOWER(2, - (Accent1 * Template->PhaseArray[Scan].Accent1Amp
  341.                         + Accent2 * Template->PhaseArray[Scan].Accent2Amp
  342.                         + Accent3 * Template->PhaseArray[Scan].Accent3Amp
  343.                         + Accent4 * Template->PhaseArray[Scan].Accent4Amp
  344.                         + (FLN(FrequencyHertz / Template->PhaseArray[Scan].FrequencyAmpNormalization)
  345.                         / (float)LOG2) * Template->PhaseArray[Scan].FrequencyAmpRolloff)));
  346.  
  347.                 /* append to the list */
  348.                 Phase->PhaseLink = NIL;
  349.                 if (PhaseTail != NIL)
  350.                     {
  351.                         PhaseTail->PhaseLink = Phase;
  352.                     }
  353.                  else
  354.                     {
  355.                         State->CurrentPhaseRecord = Phase;
  356.                         State->PhaseListHead = Phase;
  357.                     }
  358.                 PhaseTail = Phase;
  359.  
  360.                 /* adjust initial countdown */
  361.                 if (Scan < Template->Origin)
  362.                     {
  363.                         /* this occurs before the origin, so add it in */
  364.                         State->PreOriginTime += Phase->Duration;
  365.                     }
  366.             }
  367.         *PreOriginTime = State->PreOriginTime;
  368.  
  369.         return State;
  370.     }
  371.  
  372.  
  373. /* when all envelopes have been computed, then the total (i.e. largest) pre-origin */
  374. /* time will be known and we can tell all envelopes how long they must wait */
  375. /* before starting */
  376. void                                EnvelopeStateFixUpInitialDelay(EvalEnvelopeRec* State,
  377.                                             long MaximumPreOriginTime)
  378.     {
  379.         CheckPtrExistence(State);
  380.         DebugCheckState(State);
  381.  
  382.         State->LinearTransitionCounter = MaximumPreOriginTime - State->PreOriginTime;
  383.         State->LinearTransitionTotalDuration = MaximumPreOriginTime - State->PreOriginTime;
  384.     }
  385.  
  386.  
  387. /* perform a single cycle of the envelope and return the amplitude for it's */
  388. /* point.  should be called at key-down to obtain initial amplitude. */
  389. FastFixedType                EnvelopeUpdate(EvalEnvelopeRec* State)
  390.     {
  391.         CheckPtrExistence(State);
  392.         DebugCheckState(State);
  393.         return (*State->EnvelopeUpdate)(State);
  394.     }
  395.  
  396.  
  397. /* find out if envelope has reached the end */
  398. MyBoolean                        IsEnvelopeAtEnd(EvalEnvelopeRec* State)
  399.     {
  400.         CheckPtrExistence(State);
  401.         DebugCheckState(State);
  402.         return State->EnvelopeHasFinished;
  403.     }
  404.  
  405.  
  406. /* create key-up impulse.  call this before calling EnvelopeUpdate during a */
  407. /* given cycle.  this call preserves the current level of the envelope but */
  408. /* skips to the phase after the particular sustain. */
  409. void                                EnvelopeKeyUpSustain1(EvalEnvelopeRec* State)
  410.     {
  411.         CheckPtrExistence(State);
  412.         DebugCheckState(State);
  413.  
  414.         if (State->Phase <= State->SustainPhase1)
  415.             {
  416.                 /* find out if we should skip ahead to the sustain point */
  417.                 if ((State->SustainPhase1Type == eEnvelopeSustainPointSkip)
  418.                     || (State->SustainPhase1Type == eEnvelopeReleasePointSkip))
  419.                     {
  420.                         while ((State->CurrentPhaseRecord != NIL)
  421.                             && (State->Phase < State->SustainPhase1))
  422.                             {
  423.                                 State->Phase += 1;
  424.                                 State->CurrentPhaseRecord = State->CurrentPhaseRecord->PhaseLink;
  425.                             }
  426.                         State->SustainPhase1 = -1;
  427.                         EnvStepToNextInterval(State);
  428.                         return;
  429.                     }
  430.             }
  431.         if (State->Phase < State->SustainPhase1)
  432.             {
  433.                 /* if we haven't even reached the sustain phase, then cancel the sustain */
  434.                 /* phase so that it can't happen */
  435.                 State->SustainPhase1 = -1;
  436.             }
  437.         else if (State->Phase == State->SustainPhase1)
  438.             {
  439.                 /* or, if we are sustaining, then break the sustain */
  440.                 State->SustainPhase1 = -1;
  441.                 if (State->EnvelopeUpdate == &EnvUpdateSustain)
  442.                     {
  443.                         /* we are sustaining, so break it */
  444.                         EnvStepToNextInterval(State);
  445.                     }
  446.                 /* else we haven't reached it, but we broke it above */
  447.             }
  448.         /* otherwise, we must be past it so just ignore */
  449.     }
  450.  
  451.  
  452. /* create key-up impulse.  call this before calling EnvelopeUpdate during a */
  453. /* given cycle.  this call preserves the current level of the envelope but */
  454. /* skips to the phase after the particular sustain. */
  455. void                                EnvelopeKeyUpSustain2(EvalEnvelopeRec* State)
  456.     {
  457.         CheckPtrExistence(State);
  458.         DebugCheckState(State);
  459.  
  460.         if (State->Phase <= State->SustainPhase2)
  461.             {
  462.                 /* find out if we should skip ahead to the sustain point */
  463.                 if ((State->SustainPhase2Type == eEnvelopeSustainPointSkip)
  464.                     || (State->SustainPhase2Type == eEnvelopeReleasePointSkip))
  465.                     {
  466.                         while ((State->CurrentPhaseRecord != NIL)
  467.                             && (State->Phase < State->SustainPhase2))
  468.                             {
  469.                                 State->Phase += 1;
  470.                                 State->CurrentPhaseRecord = State->CurrentPhaseRecord->PhaseLink;
  471.                             }
  472.                         State->SustainPhase2 = -1;
  473.                         EnvStepToNextInterval(State);
  474.                         return;
  475.                     }
  476.             }
  477.         if (State->Phase < State->SustainPhase2)
  478.             {
  479.                 /* if we haven't even reached the sustain phase, then cancel the sustain */
  480.                 /* phase so that it can't happen */
  481.                 State->SustainPhase2 = -1;
  482.             }
  483.         else if (State->Phase == State->SustainPhase2)
  484.             {
  485.                 /* or, if we are sustaining, then break the sustain */
  486.                 State->SustainPhase2 = -1;
  487.                 if (State->EnvelopeUpdate == &EnvUpdateSustain)
  488.                     {
  489.                         /* we are sustaining, so break it */
  490.                         EnvStepToNextInterval(State);
  491.                     }
  492.                 /* else we haven't reached it, but we broke it above */
  493.             }
  494.         /* otherwise, we must be past it so just ignore */
  495.     }
  496.  
  497.  
  498. /* create key-up impulse.  call this before calling EnvelopeUpdate during a */
  499. /* given cycle.  this call preserves the current level of the envelope but */
  500. /* skips to the phase after the particular sustain. */
  501. void                                EnvelopeKeyUpSustain3(EvalEnvelopeRec* State)
  502.     {
  503.         CheckPtrExistence(State);
  504.         DebugCheckState(State);
  505.  
  506.         if (State->Phase <= State->SustainPhase3)
  507.             {
  508.                 /* find out if we should skip ahead to the sustain point */
  509.                 if ((State->SustainPhase3Type == eEnvelopeSustainPointSkip)
  510.                     || (State->SustainPhase3Type == eEnvelopeReleasePointSkip))
  511.                     {
  512.                         while ((State->CurrentPhaseRecord != NIL)
  513.                             && (State->Phase < State->SustainPhase3))
  514.                             {
  515.                                 State->Phase += 1;
  516.                                 State->CurrentPhaseRecord = State->CurrentPhaseRecord->PhaseLink;
  517.                             }
  518.                         State->SustainPhase3 = -1;
  519.                         EnvStepToNextInterval(State);
  520.                         return;
  521.                     }
  522.             }
  523.         if (State->Phase < State->SustainPhase3)
  524.             {
  525.                 /* if we haven't even reached the sustain phase, then cancel the sustain */
  526.                 /* phase so that it can't happen */
  527.                 State->SustainPhase3 = -1;
  528.             }
  529.         else if (State->Phase == State->SustainPhase3)
  530.             {
  531.                 /* or, if we are sustaining, then break the sustain */
  532.                 State->SustainPhase3 = -1;
  533.                 if (State->EnvelopeUpdate == &EnvUpdateSustain)
  534.                     {
  535.                         /* we are sustaining, so break it */
  536.                         EnvStepToNextInterval(State);
  537.                     }
  538.                 /* else we haven't reached it, but we broke it above */
  539.             }
  540.         /* otherwise, we must be past it so just ignore */
  541.     }
  542.  
  543.  
  544. /* update routine for linear-absolute intervals */
  545. static FastFixedType    EnvUpdateLinearAbsolute(EvalEnvelopeRec* State)
  546.     {
  547.         /* decrement the counter */
  548.         State->LinearTransitionCounter -= 1;
  549.  
  550.         /* see if we should advance to the next state */
  551.         if (State->LinearTransitionCounter < 0)
  552.             {
  553.                 /* yup */
  554.                 EnvStepToNextInterval(State);
  555.                 /* a new function is now in charge, so defer to it */
  556.                 return (*State->EnvelopeUpdate)(State);
  557.             }
  558.          else
  559.             {
  560.                 /* nope, we need to compute the next value */
  561.                 State->LastOutputtedValue = LinearTransitionUpdate(State->LinearTransition);
  562.                 return State->LastOutputtedValue;
  563.             }
  564.     }
  565.  
  566.  
  567. /* update routine for linear-decibel intervals */
  568. static FastFixedType    EnvUpdateLinearDecibels(EvalEnvelopeRec* State)
  569.     {
  570.         /* decrement the counter */
  571.         State->LinearTransitionCounter -= 1;
  572.  
  573.         /* see if we should advance to the next state */
  574.         if (State->LinearTransitionCounter < 0)
  575.             {
  576.                 /* yup */
  577.                 EnvStepToNextInterval(State);
  578.                 /* a new function is now in charge, so defer to it */
  579.                 return (*State->EnvelopeUpdate)(State);
  580.             }
  581.          else
  582.             {
  583.                 float                                Index0To1;
  584.                 long double                    NowDecibels; /* intermediate -- long double */
  585.                 MyBoolean                        Negative;
  586.  
  587.                 /* we need to compute the next value */
  588.                 /*State->LastOutputtedValue = LinearTransitionUpdate(State->LinearTransition);*/
  589.                 if (State->LinearTransitionTotalDuration > 1)
  590.                     {
  591.                         Index0To1 = 1 - ((float)State->LinearTransitionCounter
  592.                             / (State->LinearTransitionTotalDuration - 1));
  593.                     }
  594.                  else
  595.                     {
  596.                         Index0To1 = 1;
  597.                     }
  598.                 NowDecibels = (State->FinalDecibels * Index0To1)
  599.                     + (State->InitialDecibels * (1 - Index0To1));
  600.                 Negative = False;
  601.                 if (NowDecibels < 0)
  602.                     {
  603.                         NowDecibels = - NowDecibels;
  604.                         Negative = True;
  605.                     }
  606.                 /* some funny stuff might go on here since we're treating the FastFixed */
  607.                 /* numbers as integers, but it shouldn't matter since the curve should look */
  608.                 /* the same if the ratio of start to finish is the same no matter what */
  609.                 /* the actual magnitudes are. */
  610.                 /* in fact, the exponential base doesn't matter: */
  611.                 /*  exp((ln 2 + ln 3) / 2) = 2.4494897427831781 */
  612.                 /*  10^((20*log 2 + 20*log 3) / 2 / 20) = 2.4494897427831781 */
  613.                 State->LastOutputtedValue = FEXP(NowDecibels);
  614.                 if (Negative)
  615.                     {
  616.                         State->LastOutputtedValue = - State->LastOutputtedValue;
  617.                     }
  618.                 return State->LastOutputtedValue;
  619.             }
  620.     }
  621.  
  622.  
  623. /* sustain on a particular value */
  624. static FastFixedType    EnvUpdateSustain(EvalEnvelopeRec* State)
  625.     {
  626.         return State->LastOutputtedValue;
  627.     }
  628.  
  629.  
  630. /* routine to step to the next non-zero width interval */
  631. static void                        EnvStepToNextInterval(EvalEnvelopeRec* State)
  632.     {
  633.         OneEnvPhaseRec*            CurrentPhase;
  634.  
  635.         /* first, check to see if we should sustain */
  636.         if ((State->Phase >= 0)
  637.             && (((State->Phase == State->SustainPhase1)
  638.                 && ((State->SustainPhase1Type == eEnvelopeSustainPointSkip)
  639.                 || (State->SustainPhase1Type == eEnvelopeSustainPointNoSkip)))
  640.             ||
  641.             ((State->Phase == State->SustainPhase2)
  642.                 && ((State->SustainPhase2Type == eEnvelopeSustainPointSkip)
  643.                 || (State->SustainPhase2Type == eEnvelopeSustainPointNoSkip)))
  644.             ||
  645.             ((State->Phase == State->SustainPhase3)
  646.                 && ((State->SustainPhase3Type == eEnvelopeSustainPointSkip)
  647.                 || (State->SustainPhase3Type == eEnvelopeSustainPointNoSkip)))))
  648.             {
  649.                 /* yup, sustain */
  650.                 State->EnvelopeUpdate = &EnvUpdateSustain;
  651.                 return;
  652.             }
  653.  
  654.         /* if no sustain, then we can advance to the next phase */
  655.         State->Phase += 1;
  656.         CurrentPhase = State->CurrentPhaseRecord;
  657.         if (CurrentPhase == NIL)
  658.             {
  659.                 /* oh, look, no more phases, so we must be done.  just sustain */
  660.                 /* the last value indefinitely */
  661.                 State->EnvelopeUpdate = &EnvUpdateSustain;
  662.                 State->EnvelopeHasFinished = True;
  663.                 return;
  664.             }
  665.          else
  666.             {
  667.                 State->CurrentPhaseRecord = State->CurrentPhaseRecord->PhaseLink;
  668.             }
  669.  
  670.         /* well, we actually have to do some work. */
  671.         DebugCheckPhase(CurrentPhase);
  672.         if (CurrentPhase->Duration > 0)
  673.             {
  674.                 /* if duration is greater than 0, then we go normally */
  675.                 State->LinearTransitionTotalDuration = CurrentPhase->Duration;
  676.                 State->LinearTransitionCounter = State->LinearTransitionTotalDuration;
  677.                 /* figure out what routine to use */
  678.                 switch (CurrentPhase->TransitionType)
  679.                     {
  680.                         default:
  681.                             EXECUTE(PRERR(ForceAbort,"EnvStepToNextInterval:  bad envelope curve value"));
  682.                             break;
  683.                         case eEnvelopeLinearInAmplitude:
  684.                             State->EnvelopeUpdate = &EnvUpdateLinearAbsolute;
  685.                             switch (CurrentPhase->TargetType)
  686.                                 {
  687.                                     default:
  688.                                         EXECUTE(PRERR(ForceAbort,
  689.                                             "EnvStepToNextInterval:  bad envelope target type"));
  690.                                         break;
  691.                                     case eEnvelopeTargetAbsolute:
  692.                                         RefillLinearTransition(State->LinearTransition,
  693.                                             State->LastOutputtedValue,CurrentPhase->FinalAmplitude,
  694.                                             State->LinearTransitionTotalDuration);
  695.                                         break;
  696.                                     case eEnvelopeTargetScaling:
  697.                                         RefillLinearTransition(State->LinearTransition,
  698.                                             State->LastOutputtedValue,
  699.                                             State->LastOutputtedValue
  700.                                                 * FastFixed2Float(CurrentPhase->FinalAmplitude),
  701.                                             State->LinearTransitionTotalDuration);
  702.                                         break;
  703.                                 }
  704.                             break;
  705.                         case eEnvelopeLinearInDecibels:
  706.                             {
  707.                                 long                            Temp;
  708.                                 MyBoolean                    Negative;
  709.  
  710.                                 /* figure out end points */
  711.                                 State->EnvelopeUpdate = &EnvUpdateLinearDecibels;
  712.                                 Temp = State->LastOutputtedValue;
  713.                                 Negative = False;
  714.                                 if (Temp < 0)
  715.                                     {
  716.                                         Temp = - Temp;
  717.                                         Negative = True;
  718.                                     }
  719.                                 if (Temp == 0)
  720.                                     {
  721.                                         Temp = 1;
  722.                                     }
  723.                                 State->InitialDecibels = FLN(Temp);
  724.                                 if (Negative)
  725.                                     {
  726.                                         State->InitialDecibels = - State->InitialDecibels;
  727.                                     }
  728.                                 switch (CurrentPhase->TargetType)
  729.                                     {
  730.                                         default:
  731.                                             EXECUTE(PRERR(ForceAbort,
  732.                                                 "EnvStepToNextInterval:  bad envelope target type"));
  733.                                             break;
  734.                                         case eEnvelopeTargetAbsolute:
  735.                                             Temp = CurrentPhase->FinalAmplitude;
  736.                                             break;
  737.                                         case eEnvelopeTargetScaling:
  738.                                             Temp = FastFixed2Float(CurrentPhase->FinalAmplitude)
  739.                                                 * State->LastOutputtedValue;
  740.                                             break;
  741.                                     }
  742.                                 Negative = False;
  743.                                 if (Temp < 0)
  744.                                     {
  745.                                         Temp = - Temp;
  746.                                         Negative = True;
  747.                                     }
  748.                                 if (Temp == 0)
  749.                                     {
  750.                                         Temp = 1;
  751.                                     }
  752.                                 State->FinalDecibels = FLN(Temp);
  753.                                 if (Negative)
  754.                                     {
  755.                                         State->FinalDecibels = - State->FinalDecibels;
  756.                                     }
  757.                             }
  758.                             break;
  759.                     }
  760.             }
  761.          else
  762.             {
  763.                 /* they want the transition immediately */
  764.                 switch (CurrentPhase->TargetType)
  765.                     {
  766.                         default:
  767.                             EXECUTE(PRERR(ForceAbort,
  768.                                 "EnvStepToNextInterval:  bad envelope target type"));
  769.                             break;
  770.                         case eEnvelopeTargetAbsolute:
  771.                             State->LastOutputtedValue = CurrentPhase->FinalAmplitude;
  772.                             break;
  773.                         case eEnvelopeTargetScaling:
  774.                             State->LastOutputtedValue = FastFixed2Float(CurrentPhase->FinalAmplitude)
  775.                                 * State->LastOutputtedValue;
  776.                             break;
  777.                     }
  778.                 /* do it again.  this will handle ties nicely too */
  779.                 EnvStepToNextInterval(State);
  780.             }
  781.     }
  782.  
  783.  
  784. /* retrigger envelopes from the origin point */
  785. void                                EnvelopeRetriggerFromOrigin(EvalEnvelopeRec* State,
  786.                                             float Accent1, float Accent2, float Accent3, float Accent4,
  787.                                             float FrequencyHertz, float Loudness, float HurryUp,
  788.                                             float TicksPerSecond, MyBoolean ActuallyRetrigger)
  789.     {
  790.         OneEnvPhaseRec*        Phase;
  791.         long                            Scan;
  792.  
  793.         CheckPtrExistence(State);
  794.         DebugCheckState(State);
  795.  
  796.         /* if we actually retrigger, then reset the state */
  797.         if (ActuallyRetrigger)
  798.             {
  799.                 State->Phase = -1;
  800.                 State->CurrentPhaseRecord = State->PhaseListHead;
  801.                 while (State->Phase < State->Origin - 1)
  802.                     {
  803.                         State->CurrentPhaseRecord = State->CurrentPhaseRecord->PhaseLink;
  804.                         CheckPtrExistence(State->CurrentPhaseRecord); /* must not become NIL */
  805.                         State->Phase += 1;
  806.                     }
  807.                 State->SustainPhase1 = State->OriginalSustainPhase1;
  808.                 State->SustainPhase2 = State->OriginalSustainPhase2;
  809.                 State->SustainPhase3 = State->OriginalSustainPhase3;
  810.                 State->LinearTransitionCounter = 0; /* force transition on next update */
  811.                 State->EnvelopeUpdate = &EnvUpdateLinearAbsolute;
  812.             }
  813.  
  814.         /* no matter what, refill the parameters */
  815.         Phase = State->PhaseListHead;
  816.         for (Scan = 0; Scan < State->NumPhases; Scan += 1)
  817.             {
  818.                 CheckPtrExistence(Phase);
  819.                 DebugCheckPhase(Phase);
  820.  
  821.                 /* fill in phase record parameters */
  822.                 PRNGCHK(State->Template->PhaseArray,&(State->Template->PhaseArray[Scan]),
  823.                     sizeof(State->Template->PhaseArray[Scan]));
  824.                 /* calculate the total duration.  the effect of accents is this: */
  825.                 /*  - the accent is the base-2 log of a multiplier for the rate.  a value of 0 */
  826.                 /*    does not change the rate.  -1 halves the rate, and 1 doubles the rate. */
  827.                 /*  - the accent scaling factor is the base-2 log for scaling the accent. */
  828.                 /*    a value of 0 eliminates the effect of the accent, a value of 1 does not */
  829.                 /*    scale the accent. */
  830.                 /*  - pitch has two factors:  normalization point and rolloff.  rolloff */
  831.                 /*    determines how much the signal will decrease with each octave.  0 */
  832.                 /*    removes effect, 1 halfs signal with each octave.  normalization point */
  833.                 /*    determines what pitch will be the invariant point. */
  834.                 Phase->Duration = TicksPerSecond * HurryUp
  835.                     * State->Template->PhaseArray[Scan].Duration
  836.                     * FPOWER(2, - (Accent1 * State->Template->PhaseArray[Scan].Accent1Rate
  837.                         + Accent2 * State->Template->PhaseArray[Scan].Accent2Rate
  838.                         + Accent3 * State->Template->PhaseArray[Scan].Accent3Rate
  839.                         + Accent4 * State->Template->PhaseArray[Scan].Accent4Rate
  840.                         + (FLN(FrequencyHertz / State->Template->PhaseArray[Scan].FrequencyRateNormalization)
  841.                         / (float)LOG2) * State->Template->PhaseArray[Scan].FrequencyRateRolloff));
  842.                 /* the final amplitude scaling values are computed similarly to the rate */
  843.                 /* scaling values. */
  844.                 Phase->FinalAmplitude = Double2FastFixed(
  845.                     State->Template->PhaseArray[Scan].EndPoint
  846.                     * State->Template->OverallScalingFactor * Loudness
  847.                     * FPOWER(2, - (Accent1 * State->Template->PhaseArray[Scan].Accent1Amp
  848.                         + Accent2 * State->Template->PhaseArray[Scan].Accent2Amp
  849.                         + Accent3 * State->Template->PhaseArray[Scan].Accent3Amp
  850.                         + Accent4 * State->Template->PhaseArray[Scan].Accent4Amp
  851.                         + (FLN(FrequencyHertz / State->Template->PhaseArray[Scan].FrequencyAmpNormalization)
  852.                         / (float)LOG2) * State->Template->PhaseArray[Scan].FrequencyAmpRolloff)));
  853.  
  854.                 /* go to the next one */
  855.                 Phase = Phase->PhaseLink;
  856.             }
  857.     }
  858.